package org.example.netty.test.bio;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author zp
 * @version 1.0
 * @description: 阻塞IO的写法 一个线程 管理一个socket连接
 * 每个线程都独自处理自己负责的socket连接的输入和输出
 * 服务器的监听线程也是独立的，任何的socket连接的输入和输出处理，不会阻塞到后面新socket连接的监听和建立，
 * 这样，服务器的吞吐量就得到了提升。早期版本的Tomcat服务器，就是这样实现的。
 *
 * 这个模型最本质的问题在于，严重依赖于线程。但线程是很”贵”的资源，主要表现在：
 *
 * 1 线程的创建和销毁成本很高，线程的创建和销毁都需要通过重量级的系统调用去完成。
 *
 * 2.线程本身占用较大内存，像Java的线程的栈内存，一般至少分配512K～1M的空间，如果系统中的线程数过千，整个JVM的内存将被耗用1G。
 *
 * 3.线程的切换成本是很高的。操作系统发生线程切换的时候，需要保留线程的上下文，然后执行系统调用。过多的线程频繁切换带来的后果是，
 * 可能执行线程切换的时间甚至会大于线程执行的时间，这时候带来的表现往往是系统CPU sy值特别高（超过20%以上)的情况，导致系统几乎陷入不可用的状态。
 *
 * @date 2023/2/18 21:32
 */

public class ConnectionPerThreadWithPool implements Runnable {
    @Override
    public void run() {
        //线程池
        //注意，生产环境不能这么用，具体请参考《java高并发核心编程卷2》
        ExecutorService executor = Executors.newFixedThreadPool(100);
        try {
            //服务器监听socket
            ServerSocket serverSocket =
                    new ServerSocket(NioDemoConfig.SOCKET_SERVER_PORT);
            //主线程死循环, 等待新连接到来
            while (!Thread.interrupted()) {
                Socket socket = serverSocket.accept();
                //接收一个连接后，为socket连接，新建一个专属的处理器对象
                Handler handler = new Handler(socket);
                //创建新线程来handle
                //或者，使用线程池来处理
                new Thread(handler).start();
            }

        } catch (IOException ex) { /* 处理异常 */ }
    }

    static class Handler implements Runnable {
        final Socket socket;

        Handler(Socket s) {
            socket = s;
        }

        @Override
        public void run() {
            //死循环处理读写事件
            boolean ioCompleted = false;
            while (!ioCompleted) {
                try {
                    byte[] input = new byte[NioDemoConfig.SERVER_BUFFER_SIZE];
                    /* 读取数据 */
                    socket.getInputStream().read(input);
                    // 如果读取到结束标志
                    // ioCompleted= true
                    // socket.close();

                    /* 处理业务逻辑，获取处理结果 */
                    byte[] output = null;
                    /* 写入结果 */
                    socket.getOutputStream().write(output);
                } catch (IOException ex) { /*处理异常*/ }
            }
        }
    }
}


